package users;

import info.Conference;
import info.Manuscript;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import ui.MainPage;
import ui.Standards;

/**
 * The Program Chair class is modeled after the functions and
 * responsibilities that a Program Chair will have.  The Program Chair
 * will manage manuscript submissions for the conference he is
 * responsible for, and will distribute these submissions to individuals
 * he has designated as Subprogram Chairs.  These Subprogram Chairs will
 * aid the Program Chair in making a decision whether to accept the
 * manuscript submissions or reject them.  Acceptance is dependent on
 * the judgments of experts and the quality of the material.  Accepted
 * material is subsequently published, where it becomes available for
 * viewing on the conference site and the MSEE archives library.
 *  
 * @author Aaron Chen
 * @version 3/21/2014
 */
public class ProgramChair extends AbstractRole {
  
  /** The ID that this role is represented by. */
  public static final int ROLE_ID = 1;
  
  /** The name of this role. */
  public static final String ROLE_NAME = "Program Chair";

  /** The conference that the Program Chair is responsible for. */
  private Conference my_conference;

  /** The list of Subprogram Chairs that the Program Chair has assigned. */
  private List<Long> my_subprogram_chairs;

  /** The list of manuscripts that the Program Chair has received for
   * review from the manuscript submissions. */
  private List<Long> my_manuscripts;


  /**
   * Constructs a new Program Chair role.
   * @param the_role_id The ID for this particular role assignment.
   * @param the_user The user that this role belongs to.
   * @param the_conference The conference that the Program Chair is
   * responsible for.
   */
  public ProgramChair(final long the_role_id,
                      final User the_user,
                      final Conference the_conference) {
    super(the_role_id, the_user.getID(), the_conference.getID());
    my_conference = the_conference;
    my_subprogram_chairs = new LinkedList<Long>();
    my_manuscripts = new LinkedList<Long>();
  }
  
  /**
   * Constructs a new Program Chair role.
   * @param the_role_id The ID for this particular role assignment.
   * @param the_user_id The user that this role belongs to.
   * @param the_conference The conference that the Program Chair is
   * @param the_spcs The list of IDs of Subprogram Chairs.
   * @param the_manus The list of IDs of Manuscripts assigned to the Program Chair.
   * responsible for.
   */
  public ProgramChair(final long the_role_id,
                      final long the_user_id,
                      final Conference the_conference,
                      final List<Long> the_spcs,
                      final List<Long> the_manus) {
    super(the_role_id, the_user_id, the_conference.getID());
    my_conference = the_conference;
    my_subprogram_chairs = the_spcs;
    my_manuscripts = the_manus;
  }
  
  /**
   * Assigns a Subprogram Chair role for the Program Chair's conference.
   * @param the_user The user to be assigned as a Subprogram Chair.
   * @return true if the user was successfully assigned a Subprogram
   * Chair role; false otherwise.
   */
  public boolean assignSubprogramChairRole(final User the_user) {
    final List<Role> roles = the_user.getRoles();
    for (Role role : roles) {
      if (role.getRoleID() == Standards.ROLE_ID_SUBPROGRAM_CHAIR
          && role.getConferenceID() == my_conference.getID()) {
        return false;
      }
    }
    final SubprogramChair spc = new SubprogramChair(the_user, my_conference, this);
    the_user.addRole(spc);
    my_subprogram_chairs.add(spc.getID());
    MainPage.getDatabase().accessRole().editRole(this);
    return true;
  }

  /**
   * Assigns a manuscript to a Subprogram Chair for reviewing.  A
   * Subprogram Chair may only have a limited number of manuscripts to
   * review.  A single manuscript can only be assigned to one Subprogram
   * Chair.
   * @param the_manuscript The manuscript to be assigned.
   * @param the_spc The Subprogram Chair to receive the manuscript assignment.
   * @return true if the manuscript was assigned successfully to the
   * Subprogram Chair; false otherwise.
   */
  public boolean assignManuscriptToSubprogramChair(final Manuscript the_manuscript,
                                                   final SubprogramChair the_spc) {
    
    
    
    //TODO assignManuscriptToSubprogramChair
    return false;
  }

  /**
   * Marks the manuscript as accepted if the manuscript has not yet
   * had a decision made on it or it is before the decision deadline.
   * @param the_manuscript The manuscript to be accepted.
   * @return true if the manuscript was successfully accepted; false
   * otherwise.
   */
  public boolean acceptManuscript(final Manuscript the_manuscript) {
    final boolean result = manuscriptIsDecisionModifiable(the_manuscript);
    if (result) {
      the_manuscript.setDecisionStatus(Manuscript.STATUS_ACCEPTED);
      MainPage.getDatabase().accessManuscript().editManuscript(the_manuscript);
    }
    return result;
  }

  /**
   * Marks the manuscript as rejected if the manuscript has not yet
   * had a decision made on it or it is before the decision deadline.
   * @param the_manuscript The manuscript to be rejected.
   * @return true if the manuscript was successfully rejected; false
   * otherwise.
   */
  public boolean rejectManuscript(final Manuscript the_manuscript) {
    final boolean result = manuscriptIsDecisionModifiable(the_manuscript);
    if (result) {
      the_manuscript.setDecisionStatus(Manuscript.STATUS_REJECTED);
      MainPage.getDatabase().accessManuscript().editManuscript(the_manuscript);
    }
    return result;
  }
  
  /**
   * Determines whether a new decision can be made on a manuscript.
   * @param the_manuscript The manuscript to decide on.
   * @return true if it is before the conference's decision deadline or there
   *         is no decision made yet; false otherwise.
   */
  private boolean manuscriptIsDecisionModifiable(final Manuscript the_manuscript) {
    boolean result = false;
    final Date date = new Date(); //gets the current time.
    if (date.before(my_conference.getDecisionDeadline())
        || the_manuscript.getDecisionStatus() == Manuscript.STATUS_UNDECIDED) {
      result = true;
    }
    return result;
  }

  /** 
   * Adds a new manuscript to the Program Chair's responsibilities.
   * @param the_manu_id The ID of the manuscript.
   */
  public void assignManuscript(final long the_manu_id) {
    my_manuscripts.add(the_manu_id);
  }
  
  /** 
   * Returns the conference that the Program Chair is responsible for.
   * @return Conference my_conference
   * */
  public Conference getConference() {
    return my_conference;
  }
  
  /** 
   * Returns the list of Subprogram Chairs that the Program Chair has assigned.
   * @return List my_subprogram_chairs
   * */
  public List<Long> getSubprogramChairs() {
    return my_subprogram_chairs;
  }
  
  /** 
   * Returns the list of manuscripts that the Program Chair has received for
   * review from the manuscript submissions.
   * @return List my_manuscripts
   * */
  public List<Long> getManuscripts() {
    return my_manuscripts;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public int getRoleID() {
    return ROLE_ID;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String getRoleName() {
    return ROLE_NAME;
  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return ROLE_NAME;
  }
  
}
